<template>
	<div class="swiper-verify">
		<!--图片-->
		<div class="image-container">
			<img class="image" :src="data.image" ref="image"/>
			<img class="swiper-image" :src="data.swiperImage"
				 :style="{
				 	top: image.top,
				 	left: 0,
				 	transform: 'translateX('+mouseAction.x+'px)',
				 	width: image.swiperWidth
				}"
			/>
			<i class="refresh el-icon-refresh-left" @click="refresh"></i>
		</div>

		<!--鼠标操作滑块-->
		<div class="swiper-bar">
			<div class="bar" ref="bar">{{ translate('tips.swiperTip') }}</div>
			<span class="opacity-bar" :style="{width: mouseAction.x+'px'}"></span>
			<div class="swiper-block" :style="{left: mouseAction.x+'px',width: image.swiperWidth}" ref="swiperBlock"
				 v-html="'\u300b'">
			</div>
		</div>

		<!--隐藏的图片，用于加载完成获取源图片的宽高信息-->
		<div class="hiddenImage">
			<img :src="data.image" @load="imageComplete"/>
			<img :src="data.swiperImage" @load="swiperComplete"/>
		</div>
	</div>
</template>
<script lang="ts">
import BaseVue from "@/common/base-vue";
import Component from "vue-class-component";
import * as _ from 'lodash'
import {Emit, Prop} from "vue-property-decorator";
import SwiperVerifyModel from "./model/swiper-verify.model";
import SwiperOutputModel from "./model/swiper-output.model";
import {SwiperEventEnum} from "./enums/swiper-verify.enum";
import SwiperEventModel from "./model/swiper-event.model";
import SwiperImgSrcInfoModel from "./model/swiper-img-src-info.model";
import SwiperImgScaleInfoModel from "./model/swiper-img-scale-info.model";

@Component({components: {}})
export default class SwiperVerify extends BaseVue {

	/* 接收传入数据*/
	@Prop(Object)
	private data: SwiperVerifyModel;

	/* 用户滑动操作变量*/
	private mouseAction: SwiperEventModel = new SwiperEventModel();

	/*计时器*/
	private timeOut: NodeJS.Timeout;

	/*dom原生对象*/
	private $refs: {
		swiperBlock: HTMLDivElement,
		bar: HTMLDivElement,
		image: HTMLImageElement,
		swiperBar: HTMLDivElement
	}

	/*图片源信息数据，用于计算宽高比、位置*/
	private imageInfo: SwiperImgSrcInfoModel = new SwiperImgSrcInfoModel();

	/*大图显示的宽高信息（缩放后）*/
	private imageScale: SwiperImgScaleInfoModel = new SwiperImgScaleInfoModel();

	/*输出数据*/
	private output: SwiperOutputModel = new SwiperOutputModel();

	/**
	 * 计算属性（滑动图片宽、高度位置）
	 */
	get image() {
		return {
			top: Math.floor(this.data.top / this.imageInfo.imageHeight * 100) + '%',
			swiperWidth: Math.ceil(this.imageInfo.swiperWidth / this.imageInfo.imageWidth * 100) + '%',
		}
	}

	/**
	 * 生命周期mounted
	 */
	private mounted() {
		// 监听窗口尺寸
		window.addEventListener(SwiperEventEnum.resize, this.init, false);

		//鼠标按下
		this.$refs.swiperBlock.addEventListener(SwiperEventEnum.mousedown, this.start, false);
		//触摸按下
		this.$refs.swiperBlock.addEventListener(SwiperEventEnum.touchstart, this.start, false);

		// 鼠标移动
		document.addEventListener(SwiperEventEnum.mousemove, this.move, false);
		//触摸移动
		document.addEventListener(SwiperEventEnum.touchmove, this.move, false);

		// 鼠标放开
		document.addEventListener(SwiperEventEnum.mouseup, this.end, false);
		// 触摸结束
		document.addEventListener(SwiperEventEnum.touchend, this.end, false);
	}

	/**
	 * 大图加载完成
	 */
	private imageComplete({target}) {
		this.imageInfo.imageWidth = target.offsetWidth
		this.imageInfo.imageHeight = target.offsetHeight
		//初始化数据
		this.init();
	}

	/**
	 * 滑动图片加载完成
	 */
	private swiperComplete({target}) {
		this.imageInfo.swiperWidth = target.offsetWidth;
		this.imageInfo.swiperHeight = target.offsetHeight;
	}

	/**
	 * 初始化方法
	 */
	private init() {
		this.imageScale.width = this.$refs.image.width;
		this.imageScale.height = this.$refs.image.height;

		//计算初始化滑动图的起始位置
		this.mouseAction.x = 0;
		this.mouseAction.start = 0;
		this.mouseAction.currentX = 0;
	}

	/**
	 * 传出按下事件
	 */
	@Emit(SwiperEventEnum.start)
	private start(e: TouchEvent | MouseEvent): SwiperOutputModel {
		if (e.type === SwiperEventEnum.touchstart) {
			this.mouseAction.clickX = (e as TouchEvent).touches[0].clientX;
		}
		if (e.type === SwiperEventEnum.mousedown) {
			this.mouseAction.clickX = (e as MouseEvent).clientX;
		}
		this.mouseAction.mousedown = true;
		// 点击按下立即计时
		this.mouseAction.time = 0;
		this.setTimeout();
		return this.returnData();
	}

	/**
	 * 传出移动事件
	 */
	@Emit(SwiperEventEnum.move)
	private move(e: TouchEvent | MouseEvent): SwiperOutputModel {
		if (this.mouseAction.mousedown) {
			let moveX;
			if (e.type === SwiperEventEnum.touchmove) {
				moveX = (e as TouchEvent).touches[0].clientX - this.mouseAction.clickX;
			}
			if (e.type === SwiperEventEnum.mousemove) {
				moveX = (e as MouseEvent).clientX - this.mouseAction.clickX;
			}
			let barWidth = this.$refs.bar.offsetWidth;
			let blockWidth = this.$refs.swiperBlock.offsetWidth;

			// 如果超出范围则滑块不动
			if (moveX + this.mouseAction.currentX < 0 || moveX + this.mouseAction.currentX > barWidth - blockWidth) {
				return
			}
			this.mouseAction.x = this.mouseAction.currentX + moveX;
			return this.returnData();
		}
	}

	/**
	 * 传出放开事件
	 */
	private end() {
		if (this.mouseAction.mousedown) {
			// 放开标识
			this.mouseAction.mousedown = false;
			// 前停留的位置
			this.mouseAction.currentX = _.cloneDeep(this.mouseAction.x);
			// 计算放开结束的距离
			this.mouseAction.distance = this.mouseAction.x - this.mouseAction.start;
			// 放开结束位置
			this.mouseAction.end = _.cloneDeep(this.mouseAction.x);
			// 清除计时
			clearInterval(this.timeOut);
			// 移动距离大于0才向外传事件
			if (this.mouseAction.distance > 0) {
				return this.$emit(SwiperEventEnum.end, this.returnData());
			}
		}
	}

	/**
	 * 刷新事件
	 */
	@Emit(SwiperEventEnum.refresh)
	private refresh() {
		this.init();
	};

	/**
	 * 创建返回的数据对象
	 */
	private returnData():SwiperOutputModel {
		// 返回的开始位置不变，即原来传入的开始位置
		this.output.start = this.data.start;
		// 计算结束位置
		this.output.end = Math.ceil(this.mouseAction.end / this.imageScale.width * this.imageInfo.imageWidth);
		// 放开耗时
		this.output.time = this.mouseAction.time;
		// 放开后开始-结束的距离
		this.output.distance = Math.ceil(this.mouseAction.distance / this.imageScale.width * this.imageInfo.imageWidth);
		return this.output;
	}

	/**
	 * 计时
	 */
	private setTimeout() {
		this.timeOut = setInterval(() => {
			this.mouseAction.time += 5;
		}, 1)
	}

	/**
	 * 生命周期beforeDestroy，卸载实例移除事件
	 */
	private beforeDestroy() {
		// 移除监听窗口尺寸
		window.removeEventListener(SwiperEventEnum.resize, this.init, false);
		// 移除鼠标按下
		this.$refs.swiperBlock.removeEventListener(SwiperEventEnum.mousedown, this.start, false);
		// 移除触摸按下
		this.$refs.swiperBlock.removeEventListener(SwiperEventEnum.touchstart, this.start, false);

		// 移除鼠标移动
		document.removeEventListener(SwiperEventEnum.mousemove, this.move, false);
		// 移除触摸移动
		document.removeEventListener(SwiperEventEnum.touchmove, this.move, false);

		// 移除鼠标放开
		document.removeEventListener(SwiperEventEnum.mouseup, this.end, false);
		// 移除触摸结束
		document.removeEventListener(SwiperEventEnum.touchend, this.end, false);
	}

}
</script>
<style lang="scss" scoped>
.swiper-verify {
	.image-container {
		position: relative;

		img {
			display: block;
			margin: 0;
		}

		.image {
			width: 100%;
			height: auto;
		}

		.swiper-image {
			overflow: hidden;
			position: absolute;
			z-index: 9;
		}

		.refresh {
			font-size: 18px;
			color: #fff;
			position: absolute;
			top: 10px;
			right: 10px;
			cursor: pointer;
			text-shadow: 0 0 $base-color-grayE;
			transition: $base-transition;

			&:active {
				transform: rotate(-360deg)
			}
		}
	}

	.swiper-bar {
		position: relative;
		margin-top: 20px;
		height: 38px;
		line-height: 38px;
		overflow: hidden;
		text-align: center;
		background: #F3F5F7;
		border-radius: 5px;
		border: 1px solid #E4E7ED;

		.opacity-bar {
			position: absolute;
			height: 100%;
			top: 0;
			left: 0;
			background: #FAAB60;
			opacity: 0.5;
		}

		.swiper-block {
			height: 38px;
			cursor: move;
			color: #fff;
			background: #FAAB60;
			position: absolute;
			top: 0;
			text-indent: 8px;
			user-select: none;
		}
	}

	//隐藏的图片，用于计算宽高比
	.hiddenImage {
		width: 0;
		height: 0;
		overflow: hidden;
		position: absolute;
	}

}
</style>
